package com.edu.scnu.element;

import java.awt.Graphics;
import java.awt.Rectangle;

import javax.swing.ImageIcon;

/**
 * @说明 所有元素的基类
 * @author 14737
 */
public abstract class ElementObj {
	private int x;
	private int y;
	private int w;
	private int h;
	private int hp;
	private int speed;
	public boolean isCanRmove() {
		return isCanRmove;
	}

	public void setCanRmove(boolean isCanRmove) {
		this.isCanRmove = isCanRmove;
	}

	private ImageIcon icon;
	private boolean ishow = true;
	private boolean isCanRmove = false;
	private long bornTime;

	public boolean isIshow() {
		return ishow;
	}

	public void setIshow(boolean ishow) {
		this.ishow = ishow;
	}

	public long getBornTime() {
		return bornTime;
	}

	public void setBornTime(long bornTime) {
		this.bornTime = bornTime;
	}

	// 还有……各种必要的状态值，例如：是否生存
	private boolean live = true; // 生存状态true代表存在，false代表死亡
	// 可以采用枚举值来定义这个(生存，死亡，隐身，无敌)
	// 注明 当重新定义一个用于判定状态的变量，需要思考：1.初始化 2.值得改变 3.值的判定
	private int attack = 0;

	public ElementObj() { // 这个构造其实没有作用，只是为继承的时候不报错写的
	}

	/**
	 * 带参数的构造方法；可以由子类传输数据到父类
	 * 
	 * @param x    左上角X坐标
	 * @param y    左上角Y坐标
	 * @param w    W宽度
	 * @param h    H高度
	 * @param icon 图片
	 */
	public ElementObj(int x, int y, int w, int h, ImageIcon icon) {
		super();
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.icon = icon;
	}

	/**
	 * @说明：抽象方法，显示元素
	 * @param g 画笔 用于进行绘画
	 */
	public abstract void showElement(Graphics g);

	/**
	 * @说明 使用父类定义接收键盘事件的方法，
	 *     只有需要实现键盘监听的子类，重写这个方法(约定)
	 * @说明 方式2，使用接口的方式；使用接口方式需要在监听类进行类型转换
	 * @题外话 约定和配置，在现在大部分的java框架都是需要进行配置的。
	 *      约定优于配置
	 * @param 1.bl，true代表按下，false代表松开
	 * @param 2.key，代表触发的键盘的code值
	 * @扩展 本方法是否可以分为2个方法？1个接收按下，1个接收松开(给同学扩展使用)
	 */
	public void keyClick(boolean bl, int key) { // 这个方法不是强制必须重写的。

	}

	/**
	 * @设计模式 模板模式：在模板模式中定义对象执行方法的先后顺序，由子类选择性重写
	 *       1.移动 2.换装 3.子弹发射
	 */

	public final void model(long gameTime) {
		// 先换装
		updateImage(gameTime);
		// 再移动
		if (!this.isIshow() || !this.isLive()) {
			return;
		}
		move(gameTime);
		// 再发射子弹
		add(gameTime);
	}

	/**
	 * @说明 移动方法，需要移动的子类，需要实现这个方法
	 */
	protected void move(long gameTime) {
	}

	/**
	 * @说明 更新图片
	 */
	protected void updateImage(long gameTime) {
		if (this.getBornTime() > gameTime) {
			this.setIshow(false);
		} else {
			this.setIshow(true);
		}
	}

	/**
	 * @说明
	 */
	protected void add(long gameTime) {

	}

	// 死亡方法 给子类继承
	public void die(long gameTime) { // 死亡也是一个对象
		
	}

	public ElementObj createElement(String str) {

		return null;
	}

	/**
	 * @说明 本方法返回元素的碰撞矩形对象(实时返回)
	 * @return
	 */
	public Rectangle getRectangle() {
		// 后期可以对数据进行处理
		return new Rectangle(x, y, w, h);
	}

	/**
	 * @说明 受击方法：传入子弹的攻击力，进行计算
	 **/
	public void beAttacked(int attack) {
		this.setLive(false);
		this.setCanRmove(true);
	}

	/**
	 * @说明 碰撞方法
	 * @return boolean 返回true说明有碰撞，返回false说明没有碰撞
	 */
	public boolean pk(ElementObj obj) {
		if (!this.isIshow() || !this.isLive()) {
			return false;
		}
		return this.getRectangle().intersects(obj.getRectangle());
	}

	/**
	 * 只要是VO类POJO，就要为属性生成get和set方法
	 */

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getW() {
		return w;
	}

	public void setW(int w) {
		this.w = w;
	}

	public int getH() {
		return h;
	}

	public void setH(int h) {
		this.h = h;
	}

	public ImageIcon getIcon() {
		return icon;
	}

	public void setIcon(ImageIcon icon) {
		this.icon = icon;
	}

	public boolean isLive() {
		return live;
	}

	public void setLive(boolean live) {
		this.live = live;
	}

	public int getHp() {
		return hp;
	}

	public void setHp(int hp) {
		this.hp = hp;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public int getAttack() {
		return attack;
	}

	public void setAttack(int ack) {
		this.attack = ack;
	}

}
